//
//  SyncCloudManager.swift
//  MoodDiary
//
//  Created by 杨鸿 on 2022/1/24.
//

import Foundation
import SwiftyJSON
import CloudKit

class SyncCloudManager {
    
    static let shared = SyncCloudManager()
    
    private let recordType = "diary_dev"
    private let recordid = "diary_new"
    private let container = CKContainer(identifier: "iCloud.com.moodDiary2021").privateCloudDatabase
    
    // 拉数据
    func fetchCloud(_ completion: @escaping (_ success: Bool, _ errMsg: String) -> Void) {
        
        checkLoginStatus { isLogin,errorMsg in
            if !isLogin {
                completion(false, errorMsg)
            }
        }
        
        let fileManager = FileManager.default
        
        let predicate = NSPredicate(value: true)
        let query = CKQuery(recordType: recordType, predicate: predicate)
        container.perform(query, inZoneWith: nil) { (records, error) in
            DispatchQueue.main.async {
                print("SyncCloudManager fetchAll records:\(records), error: \(error)")
                if let recordsNotNil = records {
                    for record in recordsNotNil {
                        if let currentYear = record.value(forKey: "current_year") as? String {
                            if currentYear.count > 0 {
                                self.syncPlist(currentYear, year: "2022")
                            }
                        }
                        
                        if let lastYear = record.value(forKey: "last_year") as? String {
                            if lastYear.count > 0 {
                                self.syncPlist(lastYear, year: "2021")
                            }
                        }
                                                
                        // 富文本  attriAssetArr  、 attriAssetNameArr
                        if let attriAssetArr = record.value(forKey: "attriAssetArr") as? [CKAsset], let attriAssetNameArr = record.value(forKey: "attriAssetNameArr") as? [String] {
                            for (index, attriAsset) in attriAssetArr.enumerated() {
                                if let asseturl = attriAsset.fileURL {
                                    if let data = try? Data(contentsOf: asseturl) {
                                        var saveurl = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
                                        if index < attriAssetNameArr.count {
                                            saveurl?.appendPathComponent(attriAssetNameArr[index])
                                            do {
                                                try data.write(to: saveurl!)
                                                print("富文本 写入成功 saveurl: [\(saveurl!)]")
                                            } catch {
                                                print(error)
                                            }
                                        }
                                        
                                    }
                                }
                            }
                        }
                        
                        // diary
                        if let diary = record.value(forKey: "diary_plist") as? String {
                            if diary.count > 0 {
                                self.syncDefaultArrPlist(diary, fileName: "diary.plist")
                            }
                        }
                        
                        // mood
                        if let mood = record.value(forKey: "mood_plist") as? String {
                            if mood.count > 0 {
                                self.syncDefaultArrPlist(mood, fileName: "mood.plist")
                            }
                        }
                        
                        
                        // weather
                        if let weather = record.value(forKey: "weather_plist") as? String {
                            if weather.count > 0 {
                                self.syncDefaultArrPlist(weather, fileName: "weather.plist")
                            }
                        }
                        
                        // activity
                        if let activity = record.value(forKey: "activity_plist") as? String {
                            if activity.count > 0 {
                                self.syncDefaultArrPlist(activity, fileName: "activity.plist")
                            }
                        }
                        
                        // userDefault
                        if let feelingImageNames = record.value(forKey: "feeling_imageNames") as? String {
                            if let arr = JSON(parseJSON: feelingImageNames).arrayObject as? [[String:Any]] {
                                UserDefaults.standard.setValue(arr, forKey: KUSERFeelingImagesArrName)
                                UserDefaults.standard.synchronize()
                            }
                        }
                        
                        if let feeling_imageNames_deleted = record.value(forKey: "feeling_imageNames_deleted") as? String {
                            if let arr = JSON(parseJSON: feeling_imageNames_deleted).arrayObject as? [[String:Any]] {
                                UserDefaults.standard.setValue(arr, forKey: KUSERFeelingDeletedImagesArrName)
                                UserDefaults.standard.synchronize()
                            }
                        }
                        
                        if let activityImageNames = record.value(forKey: "activity_imageNames") as? String {
                            if let arr = JSON(parseJSON: activityImageNames).arrayObject as? [[String:Any]] {
                                UserDefaults.standard.setValue(arr, forKey: KUSERActiveImagesArrName)
                                UserDefaults.standard.synchronize()
                            }
                        }
                        
                        if let activity_imageNames_deleted = record.value(forKey: "activity_imageNames_deleted") as? String {
                            if let arr = JSON(parseJSON: activity_imageNames_deleted).arrayObject as? [[String:Any]] {
                                UserDefaults.standard.setValue(arr, forKey: KUSERActiveDeletedImagesArrName)
                                UserDefaults.standard.synchronize()
                            }
                        }
                        
                    }
                    completion(true, "")
                }

            }
        }
    }
    
    // 同步到云
    func syncCloud(completion: @escaping (_ success: Bool, _ errMsg: String) -> Void) {
        
        DispatchUtils.dispatchAfterGap(10) { [weak self] in
            guard let strongSelf =  self else { return }
            strongSelf.checkLoginStatus { isLogin,errorMsg in
                if !isLogin {
                    completion(false, errorMsg)
                }
            }
            
            let recordID = CKRecord.ID.init(recordName:strongSelf.recordid)
            let record = CKRecord.init(recordType: strongSelf.recordType, recordID: recordID)
           
            // 同步年份的文件夹
            // 今年
            let currentYearDict = strongSelf.loadLocalFileData(withYear: "2022")
            if let currentYearString = strongSelf.convertToString(withJsonObject: currentYearDict) {
                record.setValue(currentYearString, forKey: "current_year")
            }
            
            // 去年
            let lastYearDict = strongSelf.loadLocalFileData(withYear: "2021")
            if let lastYearString = strongSelf.convertToString(withJsonObject: lastYearDict) {
                record.setValue(lastYearString, forKey: "last_year")
            }
            
            // 同步diary.plist
            let diaryArr = strongSelf.loadDefaultArrayPlist("diary.plist")
            if let diaryString = strongSelf.convertToString(withJsonObject: diaryArr) {
                record.setValue(diaryString, forKey: "diary_plist")
            }
            
            // 同步mood.plist
            let moodArr = strongSelf.loadDefaultArrayPlist("mood.plist")
            if let moodString = strongSelf.convertToString(withJsonObject: moodArr) {
                record.setValue(moodString, forKey: "mood_plist")
            }
            
            // 同步weather.plist
            let weatherArr = strongSelf.loadDefaultArrayPlist("weather.plist")
            if let weatherString = strongSelf.convertToString(withJsonObject: weatherArr) {
                record.setValue(weatherString, forKey: "weather_plist")
            }
            
            // 同步activity.plist
            let activityArr = strongSelf.loadDefaultArrayPlist("activity.plist")
            if let activityString = strongSelf.convertToString(withJsonObject: activityArr) {
                record.setValue(activityString, forKey: "activity_plist")
            }
            
            // 上传图文混排.txt
            let fileManager = FileManager.default
            let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! as String
            do {
                let fileNames: [String] = try fileManager.contentsOfDirectory(atPath: docPath)
                var assetArr: [CKAsset] = []
                var assetNameArr: [String] = []
                for fileName in fileNames {
                    if fileName.hasSuffix(".txt") {
                        let attriPath = docPath + "/" + fileName
                        if fileManager.fileExists(atPath: attriPath) {
                            let assetURL = URL(fileURLWithPath: attriPath)
                            let asset = CKAsset(fileURL: assetURL)
                            assetNameArr.append(fileName)
                            assetArr.append(asset)
                        }
                    }
                }
                if !assetArr.isEmpty {
                    record.setValue(assetNameArr, forKey: "attriAssetNameArr")
                    record.setValue(assetArr, forKey: "attriAssetArr")
                }
            } catch {
                print(error)
            }
            
            // 存userDefault
            if let feelingImgArray = UserDefaults.standard.array(forKey: KUSERFeelingImagesArrName) as? [[String:Any]] {
                if let arrayString = strongSelf.convertToString(withJsonObject: feelingImgArray) {
                    record.setValue(arrayString, forKey: "feeling_imageNames")
                }
            }
            
            if let feeling_imageNames_deleted = UserDefaults.standard.array(forKey: KUSERFeelingDeletedImagesArrName) as? [[String:Any]] {
                if let arrayString = strongSelf.convertToString(withJsonObject: feeling_imageNames_deleted) {
                    record.setValue(arrayString, forKey: "feeling_imageNames_deleted")
                }
            }
            
            if let activityImgArray = UserDefaults.standard.array(forKey: KUSERActiveImagesArrName) as? [[String:Any]] {
                if let arrayString = strongSelf.convertToString(withJsonObject: activityImgArray) {
                    record.setValue(arrayString, forKey: "activity_imageNames")
                }
            }
            
            if let activity_imageNames_deleted = UserDefaults.standard.array(forKey: KUSERActiveDeletedImagesArrName) as? [[String:Any]] {
                if let arrayString = strongSelf.convertToString(withJsonObject: activity_imageNames_deleted) {
                    record.setValue(arrayString, forKey: "activity_imageNames_deleted")
                }
            }
            
            
            
            strongSelf.container.delete(withRecordID: recordID) { tempRecordID, deleteError in
                
                strongSelf.container.save(record) { savedRecord, error in
                    DispatchQueue.main.async {
                        print("SyncCloudManager savedRecord:\(savedRecord), error: \(error)")
                        if error == nil {
                            completion(true, "同步到云成功")
                        }
                    }
                }
            }
            
        }
    }
    
    private func convertToString(withJsonObject obj: Any) -> String? {
        guard let data = try? JSONSerialization.data(withJSONObject: obj, options: []) else {
            return nil
        }
        
        return String(data: data, encoding: .utf8)
    }
    
    private func syncDefaultArrPlist(_ jsonString: String, fileName: String) {
        
        let jsonData:Data = jsonString.data(using: .utf8)!
        var array = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as? NSArray
        if array == nil {
            array = NSArray.init()
        }
        
        let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! as String
        array?.write(toFile: docPath + "/" + fileName, atomically: true)
        
//        if let dataArr = JSON(parseJSON: jsonString) as? NSArray {
////            if dataArr.isEmpty {
////                return
////            }
////            if let fileArr = [dict] as? NSArray {
//                // 从icoud同步之后 缓存到本地
//                let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! as String
//            dataArr.write(toFile: docPath + "/" + fileName, atomically: true)
////            }
//        }
    }
    
    
    private func syncPlist(_ jsonString: String, year: String) {
        guard let yearDict = JSON(parseJSON: jsonString).dictionaryObject as? [String: [String: [[String: Any]]]] else {
            return
        }
        
        // 从icoud同步之后 缓存到本地
        let fileManager = FileManager.default
        let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! as String
        let folderPath = docPath + "/" + year  + "/"
        
        // 不存在 需要去创建
        if !fileManager.fileExists(atPath: folderPath) {
            do {
                try fileManager.createDirectory(atPath: folderPath, withIntermediateDirectories: true, attributes: nil)
            } catch {
                print(error)
            }
        }
        
        for i in 1...12 {
            let fileName = String(format: "%02d.plist", i)
            if let monthDict = yearDict[fileName] {
                let monthSavePath = folderPath + fileName
                (monthDict as NSDictionary).write(toFile: monthSavePath, atomically: true)
            }
        }
    }
    
    private func loadLocalFileData(withYear year: String) -> [String: [String: [[String: Any]]]] {
        
        var yearDict = [String: [String: [[String: Any]]]]()
        
        let fileManager = FileManager.default
        let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! as String
        let folderPath = docPath + "/" + year + "/"
        if !fileManager.fileExists(atPath: folderPath) {
            return [:]
        }
        
        do {
            let fileNames: [String] = try fileManager.contentsOfDirectory(atPath: folderPath)

            for fileName: String in fileNames {
              
                let searchFolderPath = docPath + "/" + year
                let filePath = (searchFolderPath as NSString).appendingPathComponent(fileName)
                if fileManager.fileExists(atPath: folderPath) {
                    if let monthDic = NSDictionary(contentsOfFile: filePath) as? [String : [[String : Any]]] {
                        yearDict[fileName] = monthDic
                    }
                }
            }
            print("loadData hisDic == \(yearDict)")
        } catch {
            print(error)
        }
        
        return yearDict
    }
    
    private func loadDefaultArrayPlist(_ fileName: String) -> NSMutableArray {
        let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! as String
        let filePath = docPath + "/" + fileName
        
        var plistArr = NSMutableArray(contentsOfFile: filePath)
        if plistArr == nil {
            plistArr = NSMutableArray()
        }
        return plistArr!
    }
    
    private func checkLoginStatus(_ handler: @escaping (_ isLogin: Bool, _ errMsg: String) -> Void) {
        CKContainer.default().accountStatus{ accountStatus, error in
            if let error = error {
                print(error.localizedDescription)
            }
            DispatchQueue.main.async {
                var errorMsg = ""
                if accountStatus != .available{
                    errorMsg = "请到设置->账户->iCloud中打开iCloud权限或检查是否登录iCloud"
                    handler(false,errorMsg)
                }else{
                    handler(true,errorMsg)
                }
                
            }
        }


    }
}

public class DispatchUtils {
    public static func dispatchAfterGap(_ delay:TimeInterval, dispatchBlock:@escaping ()->()){
        DispatchQueue.main.asyncAfter(wallDeadline: .now()+delay) {
            dispatchBlock()
        }
    }
}
